home *** CD-ROM | disk | FTP | other *** search
/ Network Support Library / RoseWare - Network Support Library.iso / apidev / mgabra.arc / MGABRA.ASM next >
Assembly Source File  |  1988-12-01  |  39KB  |  1,177 lines

  1. PAGE    55,132
  2. TITLE   ABRACADABRA! MAGIC SOFTWARE TSR/TCR (Terminate Cont Running) LIBRARY
  3.  
  4. INCLUDE MGMMACS.ASM
  5.  
  6. DEINT   EQU     0e0h            ;Deinstall Interrupt
  7.  
  8. STKSAV  EQU     32
  9.  
  10. INCLUDE MGLANGC.ASM
  11.  
  12. ;------------------------------------------------
  13. ; SEGMENT DEFINITIONS
  14. ;------------------------------------------------
  15.  
  16.     EXTRN __psp:WORD
  17.  
  18. _BSS    SEGMENT WORD PUBLIC 'BSS'
  19. _BSS    ENDS
  20.  
  21. DGROUP  GROUP   _DATA, _BSS
  22. _DATA   SEGMENT WORD PUBLIC 'DATA'
  23.         ASSUME  DS:DGROUP, SS:DGROUP
  24. _DATA   ENDS
  25.  
  26. _TEXT   SEGMENT BYTE PUBLIC 'CODE'
  27.         ASSUME  CS:_TEXT
  28.  
  29.      EXTRN _tsrexit:FAR
  30.  
  31. ;------------------------------------------------
  32. ; PUBLICS - Functions you can call
  33. ;------------------------------------------------
  34.  
  35.         PUBLIC  _swpscr
  36.         PUBLIC  _hotkey
  37.         PUBLIC  _timer
  38.         PUBLIC  _swap
  39.         PUBLIC  _tsrset
  40.         PUBLIC  _swping
  41.         PUBLIC  _swapno
  42.     PUBLIC  _swapyes
  43.         PUBLIC  _status
  44.         PUBLIC  _id
  45.         PUBLIC  _putchr
  46.         PUBLIC  _conout
  47.         PUBLIC  _inkey
  48.     PUBLIC  _bykey
  49.  
  50. ;-----------------------------------------------------
  51. ; TCB (Task Control Blocks)
  52. ; Areas where various info about the processs are kept
  53. ;-----------------------------------------------------
  54.  
  55. dosprg   dw      60 dup (0)             ;TCB for TSR program
  56. tsrprg   dw      60 dup (0)             ;TCB for Interrupted program
  57.  
  58. dosprgs  db      4000 dup (0)           ;area for saving TSR's screen
  59. tsrprgs  db      4000 dup (0)           ;area for saving interrupted's screen
  60.  
  61. swptog  dw      0                       ;swapping disabled? 1 = yes
  62. scrswp  dw      0                       ;screen swap mode
  63. timed   dw      0                       ;time triggering on? 1 = yes
  64. by28    dw      0                       ;invoked within int28 call?
  65. keyswap dw      0                       ;was swapping done on key control?
  66. keypop    dw    0            ;last swap by key? (retained)
  67. period  dw      0                       ;how many 1/18sec do we run for?
  68. doswap  dw      0                       ;"I want to swap" flag
  69. inproc  dw      0                       ;busy swapping processes flag
  70. hard_bz dw      0                       ;hardware busy flag
  71. flag_28 dw      0                       ;interrupt 28 live
  72. prob28h dw      0                       ;is int28 a problem? 0 = yes
  73. videosz dw      0                       ;size of video screen
  74. videos  dw      0                       ;dynamic base of video seg
  75. videom  dw      0                       ;current video mode
  76. videop  dw      0                       ;current video page
  77. procid  dw      0                       ;this programs id number
  78. stflag  dw      0                       ;polled status
  79. errflag dw      0                       ;critical error number
  80. envadd  dw      0                       ;paragraph of environment
  81. entry   dw      0                       ;IP of TSR upon initialization
  82. indoss  dw      0                       ;dos busy flag segment
  83. indoso  dw      0                       ;dos busy flag offset
  84. init    dw      0                       ;TSR initialized?
  85. savpar  dw      0                       ;paragraphs to save
  86. add6845 dw      0                       ;address of 6845 video controller
  87. color   dw      0b800h                  ;base of color video area
  88. mono    dw      0b000h                  ;base of monochrome video area
  89. hotkey  db      0                       ;hotkey scan code
  90. hotstat db      0                       ;hot key shift key
  91. err0    db    'ABRACADABRA ERROR: $'
  92. err1    db    'Not Enough Memory$'
  93. err2    db    'Illegal Use of DOS Function Below 0CH$'
  94. err3    db    'Insufficient Memory - Language Does Not Return Excess to Dos$'
  95. err4    db    'Synchronization$'
  96. hithere db    'Source Code Is Available Dude! Walt Howard 213-477-4151'
  97. coprght db      'Copyright (c) 1988 by Walter F. Howard Jr.'
  98. vrsn    db    '1.2 For TURBO C ONLY!'
  99.  
  100. ;-------------------------------------------------------
  101. ; DOS interrupt values
  102. ; Here is where the old interrupt vectors are kept saved
  103. ;-------------------------------------------------------
  104.  
  105. disk_int label  dword                   ;int 13h (disk) vector
  106. old_13h dw      2 dup(?)
  107.  
  108. vid_int     label    dword            ;int 10h (video) vector
  109. old_10h    dw    2 dup(?)
  110.  
  111. timer_int label dword                   ;int 1ch vector
  112. old_timer dw    2 dup(?)
  113.  
  114. key_int label   dword                   ;int 9h vector
  115. old_key dw      2 dup(?)
  116.  
  117. back_int label  dword                   ;int 28h vector
  118. old_28h dw      2 dup(?)
  119.  
  120. clear_int label dword                   ;clear out tsr interrupt
  121. old_clr dw      2 dup(?)
  122.  
  123. ;------------------------------------------------
  124. ; INTERRUPT HANDLERS
  125. ;------------------------------------------------
  126.  
  127. ;------------------------------------------------
  128. ; stime - every timer tick (1/18sec) comes here
  129. ;------------------------------------------------
  130.  
  131. stime   proc    far
  132.         sti
  133.  
  134.     pushf
  135.     call     timer_int         ;pass on vector for others first
  136.  
  137.         cmp     timed, -1            ;Is time triggering enabled?
  138.         jne     time1                ;no then don't do rest of this block
  139.         cmp     doswap, 1            ;want to swap?
  140.         je      time1                ;yes then skip next section
  141.         dec     period               ;count down
  142.         cmp     period, 0            ;is it zero yet?
  143.         jg      time1                ;if no then skip next
  144.         mov     doswap, 1            ;if yes then set doswap on
  145.  
  146. time1:
  147.  
  148.         cmp     swptog, 1            ;is swapping disabled?
  149.         jne     time2                ;no? then continue
  150.         jmp     far ptr time9        ;else exit
  151.  
  152. time2:
  153.  
  154.         cmp     doswap, 1            ;is doswap on
  155.         je      time3                ;yes jump into next check
  156.         jmp     far ptr time9        ;else exit
  157.  
  158. time3:
  159.  
  160.         cmp     inproc, 0            ;are we already engaged?
  161.         je      time4                ;no then proceed to next check
  162.         jmp     far ptr time9        ;else jump out
  163.  
  164. time4:
  165.  
  166.         mov     inproc, 1            ;signal we are engaged
  167.         cmp     hard_bz, 0           ;bios service in progress?
  168.         je      time5                ;no then proceed to next check
  169.         jmp     far ptr time8        ;else exit
  170.  
  171. time5:
  172.  
  173.         cmp     prob28h, 0           ;int 28 a problem? (0 = yes)
  174.         je      time6                ;yes, goto check dos busy
  175.         cmp     flag_28, 0           ;else, is int 28 in progress?
  176.         je      time6                ;no, check for dos busy
  177.         cmp     by28, 1              ;are we currently active on a 28 int?
  178.         je      time7                ;good! we can interrupt without
  179.                                      ;checking dos busy if TSR written
  180.                                      ;to not use dos below 0ch
  181. time6:
  182.  
  183.         push    es                   ;save ES and DI
  184.         push    di
  185.         mov     es,indoss            ;get DOS segment in ES
  186.         mov     di,indoso            ;address of DOS BUSY_FLAG in DI
  187.         cmp     byte ptr es:[di],0   ;DOS service currently active?
  188.         pop     di                   ;clean up
  189.         pop     es
  190.  
  191.         je      time7                ;not busy enter SWAP routine
  192.         jmp     far ptr time8        ;else, exit
  193.  
  194. time7:
  195.  
  196.     jmp    far ptr swpprc
  197.  
  198. time8:
  199.  
  200.         mov     inproc, 0            ;no longer in process
  201.  
  202. time9:
  203.  
  204.     cmp    by28, 0
  205.     je    time10
  206.     int    28h
  207.  
  208. time10:
  209.  
  210.         iret
  211.  
  212. stime   endp
  213.  
  214. ;-----------------------------------------------------------------
  215. ; bakprc - interrupt 28 spooler interrupt almost as good as timer
  216. ;-----------------------------------------------------------------
  217.  
  218. bakprc  proc    far
  219.         sti
  220.  
  221.     pushf
  222.     call    back_int         ;pass it on for others first
  223.  
  224.         mov     flag_28, 1           ;signal that int 28 in progress
  225.         cmp     prob28h, 0           ;Will we be using dos funcs below 0ch?
  226.         jne     bak1                 ;no? good, jump to next check
  227.         mov     flag_28, 0           ;otherwise no go, have to deny
  228.         iret                         ;return to calling process
  229.  
  230. bak1:
  231.  
  232.         cmp     swptog, 1            ;is swapping disabled?
  233.         jne     bak2                 ;no? then continue
  234.         jmp     far ptr bak7         ;else exit
  235.  
  236. bak2:
  237.  
  238.         cmp     doswap, 1            ;do we have a doswap ????
  239.         je      bak3                 ;yes?? oh good! go to next check
  240.         jmp     far ptr bak7         ;no? oh well, exit
  241.  
  242. bak3:
  243.  
  244.         cmp     inproc, 0            ;are we already engaged?
  245.         je      bak4                 ;no? ok, goto next check
  246.         jmp     far ptr bak7         ;otherwise we're outta here
  247.  
  248. bak4:
  249.  
  250.         mov     inproc, 1            ;tell them I'm busy
  251.         cmp     hard_bz, 0           ;is bios service active?
  252.         je      bak5                 ;no? ok, go to swap block
  253.         jmp     far ptr bak6         ;otherwise we'll have to wait
  254.  
  255. bak5:
  256.  
  257.         mov     by28, 1
  258.         jmp    far ptr swpprc         ;swap them out
  259.  
  260. bak6:
  261.  
  262.         mov     inproc, 0            ;we are not in progress any more!
  263.  
  264. bak7:
  265.  
  266.         mov     flag_28, 0           ;int 28 no longer active
  267.     iret
  268.  
  269. bakprc  endp
  270.  
  271. ;------------------------------------------------
  272. ; kbint keyboard checker
  273. ;------------------------------------------------
  274.  
  275. kbint   proc    far
  276.         sti                           ;re-enable interrupts
  277.         push    ax                    ;save registers
  278.  
  279.         cmp     hotkey, 0             ;tsr key swapping enabled?
  280.         je      kbint2                ;if not then exit
  281.  
  282.         in      al,60h                ;get scan code from keyboard
  283.         cmp     al, hotkey            ;is it the hotkey?
  284.         jne     kbint2                ;no, then exit
  285.  
  286.         mov     ah, 2                 ;check shift key status
  287.         int     16h                   ;keyboard bios services
  288.         and     al,15                 ;remove capslock, nlock, slock,insert
  289.         cmp     al, hotstat           ;is the special key pressed?
  290.         jne     kbint2                ;no, then exit
  291.  
  292.     cmp    inproc, 1
  293.     je    kbint4
  294.  
  295.         mov     keyswap, 1            ;key was used to initiate swap
  296.         mov     doswap, 1             ;signal we want to swap processes
  297.  
  298. kbint4:
  299.  
  300.         call    kbrst                  ;reset keyboard, issue EOI
  301.         pop     ax
  302.         iret                            ;end interrupt routine
  303.  
  304. kbint2:
  305.  
  306.         pop     ax
  307.         jmp     key_int                 ;pass control on to others
  308.  
  309. kbint   endp
  310.  
  311. ;------------------------------------------------
  312. ; dchk - bios disk services interrupt
  313. ;------------------------------------------------
  314.  
  315. dchk    proc    far
  316.     sti                ;***
  317.         inc     hard_bz                 ;we are in a disk service
  318.         pushf
  319.         call    disk_int                ;into bios we goooooooooo!
  320.     pushf
  321.         dec     hard_bz                 ;ok, were done
  322.     popf
  323.         ret     2                       ;back to calling process
  324. dchk    endp
  325.  
  326. ;------------------------------------------------
  327. ; vchk - video services interrupt
  328. ;------------------------------------------------
  329.  
  330. vchk    proc    far
  331.     sti                ;***
  332.         inc     hard_bz                 ;we are in a video service
  333.         pushf
  334.         call    vid_int                 ;into bios we goooooooooo!
  335.         dec     hard_bz                 ;ok, were done
  336.         iret                            ;back to calling process
  337. vchk    endp
  338.  
  339. ;------------------------------------------------
  340. ; crerr - if critical error come here
  341. ;------------------------------------------------
  342.  
  343. crerr   proc    far
  344.         sti
  345.         iret
  346. crerr   endp
  347.  
  348. ;-----------------------------------------------------------
  349. ; Ctrl_Bk - Control Break Handler - naturally we don't
  350. ; want a TSR to abort so we disable the abort
  351. ;-----------------------------------------------------------
  352.  
  353. ctrl_bk proc    far
  354.         sti
  355.         iret
  356. ctrl_bk endp
  357.  
  358. ;------------------------------------------------
  359. ; PUBLIC FUNCTION DEFINITIONS
  360. ;------------------------------------------------
  361.  
  362. ;------------------------------------------------
  363. ; id - set this programs id number
  364. ;------------------------------------------------
  365.  
  366. _id     proc    far
  367.         LANGIN
  368.         mov     ax, PARM1
  369.         cmp     ax, 0
  370.         je      id1
  371.         mov     procid, ax
  372. id1:
  373.         mov     ax, procid
  374.         LANGRET
  375. _id     endp
  376.  
  377. ;------------------------------------------------
  378. ; status - set removability status
  379. ;------------------------------------------------
  380.  
  381. _status proc    far
  382.         LANGIN
  383.         mov     ax, PARM1            ;ax is integer value
  384.         mov     stflag, ax           ;error message
  385.         LANGRET 0
  386. _status endp
  387.  
  388. ;------------------------------------------------
  389. ; CLEAR - Clear task out
  390. ; This is a two step process first usually the calling
  391. ; program will request information to ensure the TCR is
  392. ; in a state where deinstallation is safe. The calling
  393. ; process sets it's ax to 0 and issues int DEINT. The
  394. ; TSR will return these values in these registers:
  395. ; COMMAND AX = 1
  396. ; RETURNS:
  397. ; ax = remove status value (set with the status function)
  398. ; cx = process id (set with ID function)
  399. ; bx = segment of next TSR's clear function
  400. ; dx = offset of next TSR's clear function
  401. ;
  402. ; Command 2 is almost identical to call 1 except it is assuming
  403. ; the call is made with a plain call and not an interrupt call
  404. ;
  405. ; COMMAND AX = 2
  406. ; RETURNS:
  407. ; ax = remove status value (set with the status function)
  408. ; cx = process id (set with ID function)
  409. ; bx = segment of next TSR's clear function
  410. ; dx = offset of next TSR's clear function
  411. ; Using the status function from within the TSR the programmer
  412. ; can set up a value which will indicate to the calling program
  413. ; certain things, foremost being whether or not it is
  414. ; safe to uninstal. You the programmer can decide what this
  415. ; integer value is. For example a 1 may mean files are open
  416. ; so your deinstall routine can check with the user and inform
  417. ; him of this and therefor request verification for removal.
  418. ; The register paid bx:dx returns the address of the next tsr's
  419. ; clear function. You could call it directly and poll THAT one too!
  420. ;
  421. ; The actual de-installation requires a 1 in the AX register
  422. ; This causes the TSR to return all the interrupts it has
  423. ; borrowed to their former owners. This effectively puts the
  424. ; TSR to sleep. All that the calling program must do now
  425. ; is deallocate the memory the TSR was occupying.
  426. ;
  427. ; COMMAND AX = 0
  428. ; RESETS ALL BORROWED INTERRUPTS
  429. ; RETURNS:
  430. ; ax = remove status value (set with the status function)
  431. ; bx = pointer to environment (paragraph absolute)
  432. ; cx = process id
  433. ; dx = code segment
  434. ;------------------------------------------------
  435.  
  436. clear   proc    far
  437.         sti
  438.  
  439. clear1:
  440.  
  441.         cmp     tsrprg, 1              ;Wait until all pending
  442.         je      clear1               ;situations are finished
  443.     cmp    doswap, 1
  444.     je    clear1
  445.     cmp    inproc, 1
  446.     je    clear1
  447.         cmp     ax, 0                ;remove?
  448.         je      clear2               ;if so do it
  449.         mov     ax, stflag            ;return status flag value
  450.         mov     cx, procid            ;return process id
  451.         mov     bx, old_clr[2]       ;next tsr segment
  452.         mov     dx, old_clr          ;next tsr offset
  453.         ret
  454.  
  455. clear2:
  456.  
  457.         mov     doswap, 0                    ;shut off doswap
  458.         mov     inproc, 1                    ;we are busy
  459.     mov    swptog, 1             ;disable swapping
  460.         SETINT  1ch, old_timer[2], old_timer ;restore borrowed interrupts
  461.         SETINT  28h, old_28h[2], old_28h
  462.         SETINT  9h, old_key[2], old_key
  463.         SETINT  13h, old_13h[2], old_13h
  464.     SETINT    10h, old_10h[2], old_10h
  465.         SETINT  DEINT, old_clr[2], old_clr
  466.      call    _tsrexit
  467.         push    cs                       ;return code segment to caller so it can
  468.         pop     dx                       ;deallocate this space
  469.         mov     ax, stflag                    ;return status
  470.         mov     bx, envadd                    ;return environment address
  471.         mov     cx, procid                ;return process id
  472.         ret
  473.  
  474. clear   endp
  475.  
  476. ;------------------------------------------------
  477. ; swapno - Enables/Disables swapping
  478. ;------------------------------------------------
  479.  
  480. _swapno proc    far
  481.         LANGIN
  482.         mov     swptog, 1
  483.         LANGRET 0
  484. _swapno endp
  485.  
  486. ;------------------------------------------------
  487. ; swapyes - Enables/Disables swapping
  488. ;------------------------------------------------
  489.  
  490. _swapyes proc    far
  491.          LANGIN
  492.          mov     swptog, 0
  493.          LANGRET 0
  494. _swapyes endp
  495.  
  496. ;------------------------------------------------
  497. ; timer  - Re-hooks time slice
  498. ;------------------------------------------------
  499.  
  500. _timer   proc   far
  501.          LANGIN
  502.          mov    ax, PARM1              ;are they both zero?
  503.          add    ax, PARM2
  504.          cmp    ax, 0
  505.          je     timer1                 ;if so exit
  506.          mov    timed, -1              ;else enable timer
  507.          mov    ax, PARM1
  508.          add    ax, 2
  509.      mov    bx, [dosprg+44]
  510.          mov    [dosprg+44], ax        ;store dos programs ticks
  511.          mov    ax, PARM2
  512.          add    ax, 2
  513.      mov    cx, [tsrprg+44]
  514.          mov    [tsrprg+44], ax        ;store TSR program's ticks
  515.          jmp    timer2
  516.  
  517. timer1:
  518.  
  519.          mov    timed, 2
  520.  
  521. timer2:
  522.  
  523.          mov    ah, bl
  524.      mov    al, cl
  525.          LANGRET 0
  526. _timer   endp
  527.  
  528. ;------------------------------------------------
  529. ; swap - Swap out this task enables program to
  530. ; ask for a swap under it's control
  531. ;------------------------------------------------
  532.  
  533. _swap   proc    far
  534.         LANGIN
  535.         mov     doswap, 1              ;set doswap on
  536.  
  537. swap1:
  538.  
  539.         cmp     doswap, 0              ;loop until processes are swapped
  540.         jne     swap1                  ;usually in a wink of an eye
  541.         LANGRET 0
  542. _swap   endp
  543.  
  544. ;------------------------------------------------
  545. ; hotkey - Enables/Disables hot key action
  546. ;------------------------------------------------
  547.  
  548. _hotkey proc    far
  549.         LANGIN
  550.         mov     ax, PARM1
  551.         mov     hotkey, al           ;save the key code
  552.         mov     hotstat, ah          ;save the special key code
  553.         LANGRET 0
  554. _hotkey endp
  555.  
  556. ;------------------------------------------------
  557. ; scrswp - enables screen saving
  558. ;------------------------------------------------
  559.  
  560. _swpscr proc    far
  561.         LANGIN
  562.         mov     ax, PARM1
  563.         mov     scrswp, ax           ;set swap mode
  564.         LANGRET 0
  565. _swpscr endp
  566.  
  567. ;------------------------------------------------
  568. ; swping - are processes multitasking?
  569. ;------------------------------------------------
  570.  
  571. _swping proc    far
  572.         LANGIN
  573.     mov    ax, 0
  574.     cmp    timed, -1
  575.     jne    swp1
  576.     mov    ax, 1
  577. swp1:    
  578.         LANGRET 0
  579. _swping endp
  580.  
  581. ;------------------------------------------------
  582. ; bykey - was last swap done with key?
  583. ;------------------------------------------------
  584.  
  585. _bykey    proc    far
  586.     LANGIN
  587.     mov    ax, keypop
  588.     LANGRET 
  589. _bykey    endp
  590.  
  591. ;------------------------------------------------
  592. ; inkey - Wait for and return next Keystroke
  593. ;------------------------------------------------
  594.  
  595. _inkey  proc    far
  596.         LANGIN
  597.         mov     ah, 0
  598.         int     16h
  599.         LANGRET 0
  600. _inkey  endp
  601.  
  602. ;------------------------------------------------
  603. ; conout - Output a String to the Console
  604. ;------------------------------------------------
  605.  
  606. _conout proc    far
  607.         LANGIN
  608.         mov     dx, PARM1       ;get segment of string
  609.         mov     es, PARM2       ;get offset of string
  610. conout1:
  611.         mov     bx, dx
  612.         mov     al, es:[bx]     ;get next char
  613.         cmp     al, 0           ;is it null?
  614.         je      con2
  615.         mov     ah, 14          ;prepare bios service
  616.         int     10h             ;call it
  617.         inc     dx              ;prepare for next character
  618.         jmp     conout1
  619. con2:
  620.         LANGRET 0
  621. _conout endp
  622.  
  623. ;--------------------------------------------------------------
  624. ; putchr - put character to video page
  625. ; putchr(int row, int col, int page, int att, char c)
  626. ;--------------------------------------------------------------
  627.  
  628. _putchr proc    far
  629.         LANGIN
  630.         mov     bx, PARM2       ;position cursor
  631.         mov     cx, PARM1
  632.         mov     dl, bl
  633.         mov     dh, cl
  634.         mov     bx, PARM3       ;set video page
  635.         mov     bh, bl
  636.         mov     ah, 2
  637.         int     10h             ;position cursor
  638.         mov     ax, PARM5       ;write character
  639.         mov     bx, PARM4       ;set attribute into bl
  640.         mov     dx, PARM3    ;page number
  641.         mov     bh, dl          ;page number
  642.         mov     cx, 1           ;character count
  643.         mov     ah,9            ;service number
  644.         int     10h             ;fire
  645.  
  646.         LANGRET 0
  647. _putchr endp
  648.  
  649. ;------------------------------------------------
  650. ; TSRSET(hotkey, timer, paragraphs to save, swap screens, int28)
  651. ;
  652. ; the HOTKEY is passed as a word value, high byte is
  653. ; special key scan code status and low byte is scan key status
  654. ;
  655. ;    special key (high byte)
  656. ;
  657. ;    0 = normal
  658. ;    1 = right shift
  659. ;    2 = left shift
  660. ;    4 = control
  661. ;    8 = alt
  662. ;   16 = scroll lock
  663. ;   32 = num lock
  664. ;   64 = caps lock
  665. ;  128 = insert
  666. ;
  667. ; PARAGRAPHS TO SAVE is the size of memory to reserve for
  668. ; the program when it terminates
  669. ;
  670. ; the TIMER parameters determines how many timer ticks each process
  671. ; will get. The first parameter is how many ticks the dos program
  672. ; will get and the second is how many ticks the TSR gets
  673. ; This can be used to have a program continue to run when it is
  674. ; swapped out.
  675. ;
  676. ; The next parameter is the number of paragraphs to reserve
  677. ; in memory for the TSR. If the value is zero the TSR uses
  678. ; the position of the stack pointer + 32. This uses up a lot of
  679. ; memory in a small model program but you can set the exe file
  680. ; to have a lower stack with exemod
  681. ;
  682. ; The next parameter controls the manner in which the TSR will
  683. ; manage screen when it is swapped. Each bit in this word has
  684. ; a special function.
  685. ;
  686. ;    1 = swap cursor whenever programs swap
  687. ;    2 = save screen whenever programs swap
  688. ;    4 = restore screen whenever programs swap
  689. ;    8 = swap cursor only if TSR swap by key
  690. ;   16 = save screen only if TSR swap by key
  691. ;   32 = restore screen only if TSR swap by key
  692. ;   64 = turn cursor off on swap
  693. ;  128 = turn cursor on on swap
  694. ;  256 = don't take any precautions to avoid "snow" on screen
  695. ;
  696. ; The reason for the "invoked by key" parameters is so you can have
  697. ; your TSR running in background and if the user wants it full blown
  698. ; into foreground only then will the screens swap. You wouldn't want
  699. ; the screen swapping every 1/2 second if you were running the TSR
  700. ; on the timer ticks. You TSR can poll the funtion SWPING and if its
  701. ; true (-1) then don't have it write to the screen. If it's true then
  702. ; that means your TSR has the full screen so it's ok to write to it.
  703. ; Even better is to have your TCR (Terminate Continue Running) write
  704. ; all it's output to a video page other than 1. Then when you swap it
  705. ; in all the video output it has created is live on that page.
  706. ;
  707. ; The INT28 is an option. If your TSR program uses dos services
  708. ; under 0ch you will not be able to invoke it under certain
  709. ; circumstances. That is, whenever dos is using those services.
  710. ; They are all services that deal with screen IO and keyboard
  711. ; input. For greater versatility you should write your own
  712. ; screen and keyboard I/O and never use language statements like
  713. ; PRINT and INPUT (basic) but if you must, set this parameter to
  714. ; 0. You will not be able to invoke the TSR from the COMMAND.COM
  715. ; prompt. If your program does not use dos services less than
  716. ; 0ch you can set this flag to 1 which will allow you to invoke
  717. ; it in a greater number of circumstances.
  718. ;
  719. ;------------------------------------------------
  720.  
  721. _tsrset proc    far
  722.         LANGIN
  723.         cmp     init, 1             ;is it already installed
  724.         jne     tsrset1             ;no, then install it
  725.         LANGRET 0
  726.  
  727. tsrset1:
  728.  
  729. ;------------------------------------------------
  730. ; basic setup routine
  731. ;------------------------------------------------
  732.  
  733. ;------------------------------------------------
  734. ; save environment for use in de-installing
  735. ;------------------------------------------------
  736.  
  737.         push    cs                      ;get environment
  738.         pop     bx                      ;get code segment
  739.         sub     bx, 10h                 ;get psp
  740.         push    bx                      ;push it again
  741.         pop     es                      ;get it into es
  742.         mov     bx, 2Ch                 ;get offset
  743.         mov     ax, es:[bx]             ;get envadd
  744.         mov     envadd, ax               ;save it
  745.  
  746. ;------------------------------------------------
  747. ; get paragraphs to save paramter
  748. ;------------------------------------------------
  749.  
  750.         mov     ax, PARM4               ;get value of paragraphs to save
  751.         mov     savpar, ax
  752.  
  753. ;------------------------------------------------
  754. ; some miscellaneous things
  755. ;------------------------------------------------
  756.  
  757.     mov    swptog, 1         ;disable swapping
  758.         mov     doswap, 0         ;0 out swap request
  759.         mov     keyswap, 0           ;simulate first swap by key
  760.         mov     inproc, 1            ;we are busy
  761.  
  762. ;------------------------------------------------
  763. ; save int28 compatibility parameter
  764. ;------------------------------------------------
  765.  
  766.         mov     ax, PARM6            ;get INT28 parameter
  767.         mov     prob28h, ax          ;save it
  768.  
  769. ;------------------------------------------------
  770. ; save screenswap mode parameter
  771. ;------------------------------------------------
  772.  
  773.         mov     ax, 7                ;set scrswp to saveall
  774.         mov     scrswp, ax           ;save it
  775.  
  776. ;------------------------------------------------
  777. ; save hotkey values
  778. ;------------------------------------------------
  779.  
  780.         mov     ax, PARM1               ;check for hotkey operation
  781.         cmp     ax, 0                   ;no hot key?
  782.         je      tsrset2                 ;check for timed execution
  783.         mov     hotkey, al              ;save the key code
  784.         mov     hotstat, ah             ;save the special key code
  785.  
  786. ;------------------------------------------------
  787. ; save timer tick/multitask values
  788. ;------------------------------------------------
  789.  
  790. tsrset2:
  791.  
  792.         mov     timed, 0                ;initialize value
  793.         mov     ax, PARM2               ;get timer parameters
  794.         add     ax, PARM3               ;see if they are both zero
  795.         cmp     ax, 0                   ;do we want timer operation?
  796.         je      tsrset3                 ;no?, exit this section
  797.  
  798.         mov     timed, -1               ;turn timer on
  799.         mov     ax, PARM2
  800.         add     ax, 2
  801.         mov     [dosprg+44], ax         ;store dos program's ticks
  802.  
  803.         mov     ax, PARM3
  804.         add     ax, 2
  805.         mov     [tsrprg+44], ax         ;store TSR programs ticks
  806.  
  807.         mov     period, ax              ;set first period
  808.         jmp     tsrset4
  809.  
  810. tsrset3:
  811.  
  812.         mov     timed, 2
  813.  
  814. tsrset4:
  815.  
  816. ;------------------------------------------------
  817. ; get address of dos busy flag
  818. ;------------------------------------------------
  819.  
  820.         call    getb                    ;get address of the dos flag
  821.  
  822. ;------------------------------------------------
  823. ; initialize pointers to screen save buffers
  824. ;------------------------------------------------
  825.  
  826.         mov     [dosprg+42], offset dosprgs ;set screen buffer addresses
  827.         mov     [tsrprg+42], offset tsrprgs
  828.  
  829. ;------------------------------------------------
  830. ; get base port address of 6845 video controller
  831. ;------------------------------------------------
  832.  
  833.         mov     ax, 40h                 ;get base port address of
  834.         mov     es, ax                  ;6845 video contoller chip
  835.         mov     di, 63h                 ;this is stored in the dos
  836.         mov     dx, es:[di]             ;low memory area
  837.         mov     add6845, dx
  838.  
  839. ;------------------------------------------------
  840. ; set control break and critical error addresses
  841. ;------------------------------------------------
  842.  
  843.         SETINT  23h, cs, <offset ctrl_bk> ;set control break vector
  844.         SETINT  24h, cs, <offset crerr>   ;set critical error handler
  845.  
  846. ;--------------------------------------------------------
  847. ; save our TSR's state at this point for later invocation
  848. ;--------------------------------------------------------
  849.  
  850.         pushf                           ;prepare to snapshot TSR
  851.         push    cs                      ;push CS
  852.         mov     entry, offset here
  853.         push    entry                   ;push program counter
  854.  
  855.         SAVPRC  tsrprg                  ;click! save it at this moment
  856.  
  857. here:
  858.  
  859.         cmp     init, 0                 ;are we initialized?
  860.         je      tsrset5                 ;no, then don't do next
  861.  
  862.         LANGRET 0                       ;return
  863.  
  864. tsrset5:
  865.  
  866. ;------------------------------------------------
  867. ; set up interrupt structure
  868. ;------------------------------------------------
  869.  
  870.         call    insint                  ;steal interrupts
  871.  
  872. ;------------------------------------------------
  873. ; reset video page if we changed it
  874. ;------------------------------------------------
  875.  
  876.         SETPAG  0
  877.         mov     ax, PARM5               ;restore proper swap screen param
  878.         mov     scrswp, ax
  879.  
  880. ;------------------------------------------------
  881. ; determine TSR memory default stack or set it?
  882. ; depends on passed parameter. If 0, then default
  883. ;------------------------------------------------
  884.  
  885.         mov     ax, savpar              ;get paragraphs to save
  886.         cmp     ax, -1                  ;is it -1?
  887.         je      tsrset7                 ;OK, allocate by stack
  888.     cmp    ax, 0             ;is it 0 ?
  889.     je     tsrset8            ;Allocate by 48h
  890.     jmp    tsrset6            ;else truncate at absolute
  891.  
  892. ;------------------------------------------------
  893. ; set TSR top memory to by stack location (TURBOC)
  894. ;------------------------------------------------
  895.  
  896. tsrset7:
  897.  
  898.         mov     ax, sp                  ;where is stack pointer?
  899.         mov     cl, 4                   ;divide it by 16
  900.         shr     ax, cl
  901.         push    ss                      ;get ss into dx
  902.         pop     dx
  903.         add     ax, dx                  ;add them up to absolute stack loc
  904.         push    cs                      ;where is our code segment?
  905.         pop     dx
  906.         sub     ax, dx                  ;get the total memory from cs to ss:sp
  907.         add     ax, STKSAV              ;add 32 for safety margin
  908.         mov     init, 1                 ;we are initialized!
  909.         mov     inproc, 0               ;no longer in process
  910.     mov    swptog, 0
  911.         TSR     ax                      ;terminate and stay resident
  912.  
  913. ;------------------------------------------------
  914. ; Set TSR allocation by Memory Remaining
  915. ; Here we ask DOS for more memory. What we get we
  916. ; assume is the next paragraph above our program's
  917. ; needs so we truncate here
  918. ;------------------------------------------------
  919.  
  920. tsrset8:
  921.  
  922.     mov    bx, 2000h        ;request 2 paragraphs
  923.     mov    ah, 48h            ;
  924.     int    21h                     ;result is in ax
  925.     mov    savpar, ax        ;save it
  926.     cmp    ax, 1000h
  927.     jg    noprob
  928.  
  929.     ABORT     1, err3
  930.  
  931. noprob:                    ;return our borrowed memory
  932.  
  933.     push    ax
  934.     pop    es
  935.     mov    ah, 49h
  936.     int    21h        
  937.  
  938. noprob1:
  939.  
  940.     mov    ax, savpar        ;get top paragraph
  941.     sub    ax, __psp        ;caculate difference
  942.         mov     init, 1                 ;we are initialized!
  943.         mov     inproc, 0               ;no longer in process
  944.     mov    swptog, 0
  945.         TSR     ax                      ;terminate and stay resident
  946.  
  947. ;--------------------------------------------------------------------
  948. ; adjust program size - move stack down (ax contains # paras to save)
  949. ;--------------------------------------------------------------------
  950.  
  951. tsrset6:
  952.  
  953.         push    ss                      ;get stack segment as base
  954.         pop     ax                      ;
  955.         add     ax, savpar              ;add save for new top of stack
  956.         mov     cl, 4                   ;
  957.         shl     ax, cl                  ;x 16 for offset value
  958.         mov     bx, 128                 ;how many stack para to save
  959.         mov     cx, [tsrprg+22]         ;get stack pointer we want to save
  960.  
  961.         MOVMEM  ss, cx, ss, ax, bx      ;relocate the stack to ax
  962.         mov     [tsrprg+22], ax         ;save new stack pointer!
  963.  
  964.         mov     ax, savpar              ;restore save paragraphs to ax
  965.         add     ax, STKSAV              ;add safety margin
  966.         mov     init, 1
  967.         mov     inproc, 0
  968.     mov    swptog, 0
  969.         TSR     ax                      ;terminate and use passed parameter
  970.                                         ;for memory save value
  971. _tsrset endp
  972.  
  973. ;------------------------------------------------
  974. ; INTERNAL SUPPORT FUNCTIONS
  975. ;------------------------------------------------
  976.  
  977. ;------------------------------------------------
  978. ; swapit - Swap processes
  979. ;------------------------------------------------
  980.  
  981. swapit    proc    near
  982.  
  983. swpprc:
  984.  
  985.     mov    keypop, 0          ;default keypop state
  986.         cmp     timed, 2              ;timer always off?
  987.     je    ts0
  988.  
  989.     cmp    keyswap, 1          ;was swap request by key?
  990.     jne    ts0              ;no, then go ahead and swap
  991.     mov    keypop, 1          ;preserve this one
  992.  
  993.     not    timed              ;toggle timer
  994.     cmp    [tsrprg], 1          ;tsr sleeping?
  995.     jne    ts0                 ;wake it up!
  996.  
  997.     cmp    timed, -1          ;timer off?
  998.     je    ts0               ;swap processes
  999.     call    ksw              ;swap screens only
  1000.     mov    keyswap, 0
  1001.     mov    inproc, 0
  1002.     mov    doswap, 0          ;doswap satisfied, turn it off now
  1003.     EOI
  1004.     iret
  1005.  
  1006. ts0:
  1007.  
  1008.         cmp     [tsrprg], 0    ;task1 sleeping?
  1009.         je      ts1        ;yes, then wake it up
  1010.         jmp     far ptr ts2    ;else put it to sleep and awaken task2
  1011.  
  1012. ts1:
  1013.  
  1014.         SAVPRC  dosprg
  1015.         RESPRC  tsrprg
  1016.     mov    keyswap, 0    ;reset "key did it"
  1017.     mov    inproc, 0    ;we are out of swap process now
  1018.     mov    doswap, 0       ;doswap satisfied, turn it off now
  1019.         EOI
  1020.     iret
  1021.  
  1022. ts2:
  1023.  
  1024.         SAVPRC  tsrprg
  1025.         RESPRC  dosprg
  1026.     mov    flag_28, 0
  1027.     mov    by28, 0
  1028.     mov    keyswap, 0    ;reset "key did it"
  1029.     mov    inproc, 0    ;we are out of swap process now
  1030.     mov    doswap, 0       ;doswap satisfied, turn it off now
  1031.         EOI
  1032.     iret
  1033.  
  1034. swapit    endp
  1035.  
  1036. ;------------------------------------------------
  1037. ; ksw - Swap screens only
  1038. ;------------------------------------------------
  1039.  
  1040. ksw     proc    near
  1041.     push    bp
  1042.     push    ax
  1043.     push    bx
  1044.     push    cx
  1045.     push    dx
  1046.     push    si
  1047.     push    di
  1048.     push    ds
  1049.     push     es
  1050.     pushf
  1051.  
  1052.         SAVCUR  dosprg                ;save dos programs's cursor
  1053.         SAVSCR  dosprg                ;save dos program's screen
  1054.         RESSCR  tsrprg                ;restore tsr's screen
  1055.         RESCUR  tsrprg                ;restore tsr's cursor
  1056.  
  1057.     popf
  1058.     pop     es
  1059.     pop    ds
  1060.     pop    di
  1061.     pop    si
  1062.     pop    dx
  1063.     pop    cx
  1064.     pop    bx
  1065.     pop    ax
  1066.     pop    bp
  1067.  
  1068.         ret
  1069. ksw     endp
  1070.  
  1071. ;-------------------------------------------------------
  1072. ; insint - this replaces the necessary interrupt vectors
  1073. ; Here is where all the interrupts are grabbed
  1074. ;-------------------------------------------------------
  1075.  
  1076. insint  proc    near
  1077.  
  1078.         SAVINT  9h, old_key[2], old_key
  1079.         SETINT  9h, cs, <offset kbint>
  1080.  
  1081.         SAVINT  13h, old_13h[2], old_13h
  1082.         SETINT  13h, cs, <offset dchk>
  1083.  
  1084.     SAVINT    10h, old_10h[2], old_10h
  1085.     SETINT    10h, cs, <offset vchk>
  1086.  
  1087.         SAVINT  DEINT, old_clr[2], old_clr
  1088.         SETINT  DEINT, cs, <offset clear>
  1089.         SAVINT  1ch, old_timer[2], old_timer
  1090.         SETINT  1ch, cs, <offset stime>
  1091.         SAVINT  28h, old_28h[2], old_28h
  1092.         SETINT  28h, cs, <offset bakprc>
  1093.  
  1094.         ret
  1095.  
  1096. insint  endp
  1097.  
  1098. ;------------------------------------------------
  1099. ; getb - gets the address of the dos busy flag
  1100. ;------------------------------------------------
  1101.  
  1102. getb    proc    near
  1103.         mov     ah, 34h                 ;hey Uncle Woody! lets get the
  1104.                                         ;dos busy flag address!
  1105.         int     21h
  1106.         mov     indoso,bx               ;store it in our code segment
  1107.         mov     indoss,es
  1108.         ret
  1109. getb    endp
  1110.  
  1111. ;------------------------------------------------
  1112. ; vidseg - calculates base of current video mode
  1113. ;------------------------------------------------
  1114.  
  1115. vidseg  proc    near
  1116.  
  1117.         cmp     videom, 7            ;mono mode, setup appropriately
  1118.         je      vidseg1
  1119.         cmp     videom, 1            ;40 wide screen, setup appropriately
  1120.         jle     vidseg2
  1121.                                      ;otherwise assume modes 2 or 3
  1122.         mov     ax, videop           ;get page number
  1123.         mov     dx, 100h
  1124.         mul     dx                   ;multiply by page size
  1125.         add     ax, color            ;add color base
  1126.         mov     videos, ax           ;save effective video offset
  1127.         mov     videosz, 4000        ;save page size
  1128.         jmp     vidseg3
  1129.  
  1130. vidseg1:
  1131.  
  1132.         mov     ax, videop           ;get page number
  1133.         mov     dx, 100h
  1134.         mul     dx                   ;multiply by page size
  1135.         add     ax, mono             ;add mono base
  1136.         mov     videos, ax           ;save effective video offset
  1137.         mov     videosz, 4000        ;save page size
  1138.         jmp     vidseg3
  1139.  
  1140. vidseg2:
  1141.  
  1142.         mov     ax, videop           ;get page number
  1143.         mov     dx, 80h
  1144.         mul     dx                   ;multiply by page size
  1145.         add     ax, color            ;add color base
  1146.         mov     videos, ax           ;save effective video offset
  1147.         mov     videosz, 2000        ;save page size
  1148.  
  1149. vidseg3:
  1150.  
  1151.         ret
  1152. vidseg  endp
  1153.  
  1154. ;------------------------------------------------------------------------------
  1155. ;kbrst resets the keyboard and issues an EOI to the 8259 PIC.
  1156. ;------------------------------------------------------------------------------
  1157.  
  1158. kbrst   proc    near
  1159.     cli
  1160.         in      al,61h                  ;get current control value
  1161.         mov     ah,al                   ;save it in AH
  1162.         or      al,80h                  ;set the high bit
  1163.         out     61h,al                  ;send it to the control port
  1164.         mov     al,ah                   ;recover original value
  1165.         out     61h,al                  ;send it out
  1166.         EOI                             ;hardware end of interrupt
  1167.         ret
  1168. kbrst   endp
  1169.  
  1170. _TEXT   ENDS
  1171.  
  1172.         END
  1173.  
  1174. ;------------------------------------------------
  1175. ; end of tsrlib
  1176. ;------------------------------------------------
  1177.